Skip to content

Restructure threat-model sources by controller#32

Merged
ppkarwasz merged 2 commits into
mainfrom
threat-model-sources-by-controller
Jun 25, 2026
Merged

Restructure threat-model sources by controller#32
ppkarwasz merged 2 commits into
mainfrom
threat-model-sources-by-controller

Conversation

@ppkarwasz

Copy link
Copy Markdown
Member

Restructures the "Data sources" section of the common threat model into a Sources section organised by who controls each input, rather than a flat trusted/untrusted split.

The three categories are defined by their controller:

  • Configuration (operator-controlled, trusted): environment variables, configuration properties, and configuration files, with the existing deployer responsibilities.
  • Structural identifiers and control (developer-controlled, trusted): logger names, levels, markers, the identifiers and field names of a structured log message (for example the RFC 5424 MSGID and SD-ID fields), and the format string of a parameterized log statement.
  • Content (user-controlled, untrusted): log messages, the string representation of log parameters, and thread context values.

Why

Triaging recent reports showed that reporters have a difficulty into classifying sources correctly, such as the structural identifiers of a structured message. Organising sources by controller makes the trust classification explicit and gives a clean basis for deciding which reports are in scope.

It also lets the model state the remediation rule that follows from the classification: trusted inputs may be rejected (fail-fast, for example by throwing), while user-controlled content must be accepted and never rejected, since rejecting it would turn a malicious value into a denial of service.

Thread context keys

Thread context values are classified as untrusted content. The trust level of thread context keys is deferred to discussion apache/logging-log4j2#4132 and marked in the document as a known open gap, rather than silently choosing a side.

Dependent changes

  • The adversary-capabilities section now references the new content subsection, drops thread context keys from the in-scope channels pending the discussion above, and marks an adversary who controls developer-controlled structural or control inputs as out of scope.
  • Internal cross-references updated to the new subsection anchors; the parent #threat-common-sources anchor is retained.

Out of scope for this PR

Sink-side concepts (structured versus unstructured layouts, active versus passive sinks, and downstream-destination trust) are intentionally left for a follow-up PR.

Replace the "Data sources" section's trusted/untrusted split with a "Sources" section organised by who controls each input: configuration (operator-controlled), structural identifiers and control (developer-controlled), and content (user-controlled). This makes the trust classification explicit and gives a clean basis for triaging which reports are in scope.

Thread context values are classified as untrusted content. The trust level of thread context keys is deferred to discussion apache/logging-log4j2#4132 and marked as a known open gap.

The adversary-capabilities section now references the new content subsection, drops thread context keys from the in-scope channels pending that discussion, and marks an adversary who controls developer-controlled structural or control inputs as out of scope.

Sink concepts (structured vs unstructured layouts, active vs passive sinks, downstream-destination trust) are intentionally left for a follow-up PR.

Assisted-By: Claude Opus 4.8 (1M context) <[email protected]>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR restructures the "Data sources" section of the common threat model document into a "Sources" section organized by who controls each input (operator/developer/user), making the trust classification explicit. It also aligns the adversary-capabilities section with the new categories and defers the classification of thread context keys to an external discussion, marking it as a known open gap.

Changes:

  • Replace the flat trusted/untrusted split with three controller-based subsections: Configuration (operator), Structural identifiers and control (developer), and Content (user).
  • Add an explicit remediation rule (trusted inputs may be rejected; user-controlled content must not be rejected) and move the deserialization/object-stringification guidance under Content.
  • Update adversary-capability cross-references to the new anchors, drop thread context keys from in-scope channels, and mark developer-controlled structural/control inputs as out of scope.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@FreeAndNil FreeAndNil left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should put the string conversion topic in a separate note to move it a little bit away from the bullet points before about what we don't trust?

Comment thread src/site/antora/modules/ROOT/pages/_threat-model-common.adoc Outdated
Comment thread src/site/antora/modules/ROOT/pages/_threat-model-common.adoc
@ppkarwasz ppkarwasz enabled auto-merge (squash) June 25, 2026 13:14

@FreeAndNil FreeAndNil left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ppkarwasz ppkarwasz merged commit c3de070 into main Jun 25, 2026
5 checks passed
@ppkarwasz ppkarwasz deleted the threat-model-sources-by-controller branch June 25, 2026 19:43
ppkarwasz added a commit that referenced this pull request Jul 9, 2026
Adds a Sinks section, the counterpart of the existing Sources section, closing the sink-side gap deferred in #32 ("active versus passive sinks, and downstream-destination trust").

The section states three things:

1. Sinks are the destinations an appender writes to. Unlike sources, which range from trusted configuration to untrusted content, every sink is operator-configured and therefore trusted, including destinations created dynamically at runtime (for example a Routing appender that interpolates a file path).

2. Destination integrity is a deployer responsibility. An adversary who can write to a log destination, for example by planting a symbolic link where a file appender creates its output, can already tamper with the logs directly, so the frameworks do not defend a destination they were configured to trust. A report that assumes such write access is out of scope.

3. A passive sink consumes our output as the format the layout produced, and we own the correctness of that format. An active sink re-interprets well-formed output in another language and acts on it (a terminal executing ANSI escape sequences, for example), which we do not own. The boundary is whether the framework emitted output malformed in its own format (ours to fix) or well-formed output that a sink chose to re-interpret (out of scope).

The two worked examples are precedents: CVE-2025-54812 (Log4cxx HTML layout emitting malformed HTML) is a defect we published, while the class of CVE-2025-55754 (Apache Tomcat, ANSI escape sequences interpreted by a Windows console) is one we do not treat as a vulnerability.

Dependent edits: the Log Injection threat now lists the HTML layout and cross-references the passive/active distinction; the out-of-scope adversary list adds the destination-write-access case and the active-sink re-interpretation case.

This is normative and requires PMC review before merge.

Assisted-By: Claude Opus 4.8 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants